package com.jzo2o.customer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.jzo2o.common.constants.UserType;
import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.model.CurrentUserInfo;
import com.jzo2o.common.model.PageResult;
import com.jzo2o.common.utils.CollUtils;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.customer.enums.AuditStatusEnum;
import com.jzo2o.customer.enums.CertificationStatusEnum;
import com.jzo2o.customer.mapper.AgencyCertificationMapper;
import com.jzo2o.customer.mapper.CertificationAuditMapper;
import com.jzo2o.customer.mapper.ServeProviderMapper;
import com.jzo2o.customer.mapper.WorkerCertificationMapper;
import com.jzo2o.customer.model.domain.AgencyCertification;
import com.jzo2o.customer.model.domain.CertificationAudit;
import com.jzo2o.customer.model.domain.ServeProvider;
import com.jzo2o.customer.model.domain.WorkerCertification;
import com.jzo2o.customer.model.dto.request.AgencyCertificationAuditAddReqDTO;
import com.jzo2o.customer.model.dto.request.AgencyCertificationAuditPageQueryReqDTO;
import com.jzo2o.customer.model.dto.request.WorkerCertificationAuditAddReqDTO;
import com.jzo2o.customer.model.dto.request.WorkerCertificationAuditPageQueryReqDTO;
import com.jzo2o.customer.model.dto.response.AgencyCertificationAuditResDTO;
import com.jzo2o.customer.model.dto.response.RejectReasonResDTO;
import com.jzo2o.customer.model.dto.response.WorkerCertificationAuditResDTO;
import com.jzo2o.customer.service.ICertificationAuditService;
import com.jzo2o.mvc.utils.UserContext;
import com.jzo2o.mysql.utils.PageUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 服务人员/机构认证流水表 服务实现类
 * </p>
 * @author JIAN
 * @since 2024-08-30
 */
@Service
public class CertificationAuditServiceImpl extends ServiceImpl<CertificationAuditMapper, CertificationAudit> implements ICertificationAuditService {
    @Resource
    private ServeProviderMapper serveProviderMapper;
    @Resource
    private WorkerCertificationMapper workerCertificationMapper;
    @Resource
    private AgencyCertificationMapper agencyCertificationMapper;

    @Override
    @Transactional
    public void addCertificationInfoForWorker(WorkerCertificationAuditAddReqDTO workerCertificationAuditAddReqDTO) {
        Long userId = UserContext.currentUserId();
        ServeProvider worker = serveProviderMapper.selectById(userId);
        if (ObjectUtils.isEmpty(userId) || ObjectUtils.isEmpty(worker)) {
            throw new ForbiddenOperationException("用户不存在无法认证");
        }
        if (worker.getType() != UserType.WORKER) {
            throw new ForbiddenOperationException("提交认证资料不符合用户身份");
        }

        // 更新流水表
        baseMapper.insert(CertificationAudit.builder()
                .serveProviderId(userId)
                .serveProviderType(UserType.WORKER)
                .name(workerCertificationAuditAddReqDTO.getName())
                .idCardNo(workerCertificationAuditAddReqDTO.getIdCardNo())
                .frontImg(workerCertificationAuditAddReqDTO.getFrontImg())
                .backImg(workerCertificationAuditAddReqDTO.getBackImg())
                .certificationMaterial(workerCertificationAuditAddReqDTO.getCertificationMaterial())
                .build());

        // 更新最终信息表
        WorkerCertification agencyCertification = WorkerCertification.builder()
                .id(userId)
                .certificationStatus(CertificationStatusEnum.PROGRESSING.getStatus())
                .build();
        if (ChainWrappers.lambdaQueryChain(workerCertificationMapper)
                .eq(WorkerCertification::getId, userId)
                .count() == 0) {
            workerCertificationMapper.insert(agencyCertification);
        } else {
            workerCertificationMapper.updateById(agencyCertification);
        }
    }

    @Override
    @Transactional
    public void addCertificationInfoForAgency(AgencyCertificationAuditAddReqDTO agencyCertificationAuditAddReqDTO) {
        Long userId = UserContext.currentUserId();
        ServeProvider worker = serveProviderMapper.selectById(userId);
        if (ObjectUtils.isEmpty(userId) || ObjectUtils.isEmpty(worker)) {
            throw new ForbiddenOperationException("用户不存在无法认证");
        }
        if (worker.getType() != UserType.INSTITUTION) {
            throw new ForbiddenOperationException("提交认证资料不符合用户身份");
        }

        // 更新流水表
        baseMapper.insert(CertificationAudit.builder()
                .serveProviderId(userId)
                .serveProviderType(UserType.INSTITUTION)
                .name(agencyCertificationAuditAddReqDTO.getLegalPersonName())
                .idCardNo(agencyCertificationAuditAddReqDTO.getLegalPersonIdCardNo())
                .institutionName(agencyCertificationAuditAddReqDTO.getName())
                .idNumber(agencyCertificationAuditAddReqDTO.getIdNumber())
                .businessLicense(agencyCertificationAuditAddReqDTO.getBusinessLicense())
                .build());

        // 更新最终信息表
        AgencyCertification agencyCertification = AgencyCertification.builder()
                .id(userId)
                .certificationStatus(CertificationStatusEnum.PROGRESSING.getStatus())
                .build();
        if (ChainWrappers.lambdaQueryChain(agencyCertificationMapper)
                .eq(AgencyCertification::getId, userId)
                .count() == 0) {
            agencyCertificationMapper.insert(agencyCertification);
        } else {
            agencyCertificationMapper.updateById(agencyCertification);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public RejectReasonResDTO getLatestRejectReason() {
        List<CertificationAudit> certificationAudits = lambdaQuery()
                .eq(CertificationAudit::getCertificationStatus, CertificationStatusEnum.FAIL.getStatus())
                .eq(CertificationAudit::getServeProviderId, UserContext.currentUserId())
                .orderByDesc(CertificationAudit::getCreateTime)
                .list();

        return CollUtils.isEmpty(certificationAudits)
                ? new RejectReasonResDTO()
                : new RejectReasonResDTO(certificationAudits.get(0).getRejectReason());
    }

    @Override
    public PageResult<WorkerCertificationAuditResDTO> getWorkerCertificationInfo(WorkerCertificationAuditPageQueryReqDTO pageQueryReqDTO) {
        Page<CertificationAudit> pageQuery = PageUtils.parsePageQuery(pageQueryReqDTO, CertificationAudit.class);

        String name = pageQueryReqDTO.getName();
        String idCardNo = pageQueryReqDTO.getIdCardNo();
        Integer auditStatus = pageQueryReqDTO.getAuditStatus();
        Integer certificationStatus = pageQueryReqDTO.getCertificationStatus();

        LambdaQueryWrapper<CertificationAudit> queryWrapper = Wrappers.<CertificationAudit>lambdaQuery()
                .eq(CertificationAudit::getServeProviderType, UserType.WORKER)
                .like(ObjectUtils.isNotEmpty(name), CertificationAudit::getName, name)
                .like(ObjectUtils.isNotEmpty(idCardNo), CertificationAudit::getIdCardNo, idCardNo)
                .eq(ObjectUtils.isNotEmpty(auditStatus), CertificationAudit::getAuditStatus, auditStatus)
                .eq(ObjectUtils.isNotEmpty(certificationStatus), CertificationAudit::getCertificationStatus, certificationStatus);

        return PageUtils.toPage(
                baseMapper.selectPage(pageQuery, queryWrapper),
                WorkerCertificationAuditResDTO.class);
    }

    @Override
    public PageResult<AgencyCertificationAuditResDTO> getAgencyCertificationInfo(AgencyCertificationAuditPageQueryReqDTO pageQueryReqDTO) {
        Page<CertificationAudit> pageQuery = PageUtils.parsePageQuery(pageQueryReqDTO, CertificationAudit.class);

        String name = pageQueryReqDTO.getName();
        String legalPersonName = pageQueryReqDTO.getLegalPersonName();
        Integer auditStatus = pageQueryReqDTO.getAuditStatus();
        Integer certificationStatus = pageQueryReqDTO.getCertificationStatus();

        LambdaQueryWrapper<CertificationAudit> queryWrapper = Wrappers.<CertificationAudit>lambdaQuery()
                .eq(CertificationAudit::getServeProviderType, UserType.INSTITUTION)
                .like(ObjectUtils.isNotEmpty(name), CertificationAudit::getInstitutionName, name)
                .like(ObjectUtils.isNotEmpty(legalPersonName), CertificationAudit::getName, legalPersonName)
                .eq(ObjectUtils.isNotEmpty(auditStatus), CertificationAudit::getAuditStatus, auditStatus)
                .eq(ObjectUtils.isNotEmpty(certificationStatus), CertificationAudit::getCertificationStatus, certificationStatus);

        return PageUtils.toPage(
                baseMapper.selectPage(pageQuery, queryWrapper),
                AgencyCertificationAuditResDTO.class,
                (origin, target) -> {
                    target.setName(origin.getInstitutionName());
                    target.setLegalPersonName(origin.getName());
                    target.setLegalPersonIdCardNo(origin.getIdCardNo());
                });
    }

    @Override
    @Transactional
    public void audit(Long id, Integer certificationStatus, String rejectReason) {
        CertificationAudit certificationAudit = baseMapper.selectById(id);
        if (ObjectUtils.isEmpty(certificationAudit)) {
            throw new ForbiddenOperationException("认证记录不存在无法操作");
        }

        CurrentUserInfo currentUserInfo = UserContext.currentUser();
        if (ObjectUtils.isEmpty(currentUserInfo) || ObjectUtils.isEmpty(currentUserInfo.getId())) {
            throw new ForbiddenOperationException("无法获取当前用户信息");
        }

        // 准备公共更新部分
        LocalDateTime now = LocalDateTime.now();
        certificationAudit.setCertificationStatus(certificationStatus);
        LambdaUpdateChainWrapper<CertificationAudit> updateChainWrapper = lambdaUpdate()
                .eq(CertificationAudit::getId, id)
                .set(CertificationAudit::getAuditStatus, AuditStatusEnum.AUDITED.getStatus())
                .set(CertificationAudit::getAuditTime, now)
                .set(CertificationAudit::getAuditorId, currentUserInfo.getId())
                .set(CertificationAudit::getAuditorName, currentUserInfo.getName())
                .set(CertificationAudit::getCertificationStatus, certificationStatus);

        Long serveProviderId = certificationAudit.getServeProviderId();
        if (certificationStatus == CertificationStatusEnum.FAIL.getStatus()) {
            // 认证失败
            updateChainWrapper
                    .set(CertificationAudit::getRejectReason, rejectReason)
                    .update();

            if (certificationAudit.getServeProviderType() == UserType.WORKER) {
                // 服务人员认证失败
                workerCertificationMapper.updateById(WorkerCertification.builder()
                        .id(serveProviderId)
                        .certificationStatus(certificationStatus)
                        .certificationTime(now).build());
            } else {
                // 机构认证失败
                agencyCertificationMapper.updateById(AgencyCertification.builder()
                        .id(serveProviderId)
                        .certificationStatus(certificationStatus)
                        .certificationTime(now).build());
            }

        } else {
            // 认证成功
            updateChainWrapper
                    .update();

            String name;
            if (certificationAudit.getServeProviderType() == UserType.WORKER) {
                // 服务人员认证成功
                workerCertificationMapper.updateById(WorkerCertification.builder()
                        .id(serveProviderId)
                        .name(certificationAudit.getName())
                        .idCardNo(certificationAudit.getIdCardNo())
                        .frontImg(certificationAudit.getFrontImg())
                        .backImg(certificationAudit.getBackImg())
                        .certificationMaterial(certificationAudit.getCertificationMaterial())
                        .certificationStatus(certificationStatus)
                        .certificationTime(now).build());
                name = certificationAudit.getName();
            } else {
                // 机构认证成功
                agencyCertificationMapper.updateById(AgencyCertification.builder()
                        .id(serveProviderId)
                        .name(certificationAudit.getInstitutionName())
                        .idNumber(certificationAudit.getIdNumber())
                        .legalPersonName(certificationAudit.getName())
                        .legalPersonIdCardNo(certificationAudit.getIdCardNo())
                        .businessLicense(certificationAudit.getBusinessLicense())
                        .certificationStatus(certificationStatus)
                        .certificationTime(now).build());
                name = certificationAudit.getInstitutionName();
            }

            // 更新总表中的姓名/机构名称
            ChainWrappers.lambdaUpdateChain(serveProviderMapper)
                    .eq(ServeProvider::getId, serveProviderId)
                    .set(ServeProvider::getName, name)
                    .update();
        }
    }
}